home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / lynx-2.4 / utils / inews / inews.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-28  |  7.8 KB  |  396 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)inews.c    1.16    (Berkeley) 8/27/89";
  3. #endif
  4.  
  5. /*
  6.  * Itty-bitty inews for talking to remote server.
  7.  * Simply accept input on stdin (or via a named file) and dump this
  8.  * to the server; add a From: and Path: line if missing in the original.
  9.  * Print meaningful errors from the server.
  10.  * Limit .signature files to MAX_SIGNATURE lines.
  11.  * No processing of command line options.
  12.  *
  13.  * Original by Steven Grady <grady@ucbvax.Berkeley.EDU>, with thanks from
  14.  * Phil Lapsley <phil@ucbvax.berkeley.edu>
  15.  * Send bug reports to Stan Barber <sob@bcm.tmc.edu>
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <pwd.h>
  20. #include <ctype.h>
  21. #include "conf.h"
  22. #include "nntp.h"
  23. #ifndef FOR_NN
  24. #ifdef USG
  25. #include <string.h>
  26. #else not USG
  27. #include <strings.h>
  28. #endif not USG
  29. #endif
  30.  
  31. #define    MAX_SIGNATURE    4
  32.  
  33. extern    FILE    *ser_wr_fp;
  34.  
  35. char    host_name[256];
  36.  
  37. main(argc, argv)
  38. int    argc;
  39. char    *argv[];
  40. {
  41.     char    line[NNTP_STRLEN], s[NNTP_STRLEN];
  42.     int    seen_fromline, in_header, seen_header;
  43.     int    response;
  44.     char    *server;
  45.     char    *getserverbyfile();
  46.     register char    *cp;
  47.  
  48.     ++argv;
  49.     while (argc > 1)
  50.         if (*argv[0] == '-') {
  51.             ++argv;
  52.             --argc;
  53.         } else
  54.             break;
  55.  
  56.     if (argc > 1) {
  57.         if (freopen(*argv, "r", stdin) == NULL) {
  58.             perror(*argv);
  59.             exit(1);
  60.         }
  61.     }
  62.  
  63.     uname(host_name);
  64.  
  65.     server = getserverbyfile(SERVER_FILE);
  66.     if (server == NULL) {
  67.         fprintf(stderr,
  68.             "Can't get the name of the news server from %s.\n",
  69.             SERVER_FILE);
  70.         fprintf(stderr,
  71.            "Either fix this file, or put NNTPSERVER in your enviroment.\n");
  72.         exit(1);
  73.     }
  74.  
  75.     response = server_init(server);
  76.     if (response < 0) {
  77.         printf("Couldn't connect to %s news server, try again later.\n",
  78.             server);
  79.         exit(1);
  80.     }
  81.  
  82.     if (handle_server_response(response, server) < 0
  83.         || response == OK_NOPOST) {
  84.         close_server();
  85.         exit(1);
  86.     }
  87.  
  88.     put_server("POST");
  89.     (void) get_server(line, sizeof(line));
  90.     if (*line != CHAR_CONT) {
  91.         if (atoi(line) == ERR_NOPOST) {
  92.             close_server();
  93.             fprintf(stderr,
  94.                 "Sorry, you can't post from this machine.\n");
  95.             exit(1);
  96.         } else {
  97.             close_server();
  98.                 fprintf(stderr, "Remote error: %s\n", line);
  99.             exit(1);
  100.         }
  101.     }
  102.  
  103.     in_header = 1;
  104.     seen_header = 0;
  105.     seen_fromline = 0;
  106.  
  107.     while (gets(s) != NULL) {
  108.         if (s[0] == '.')    /* Single . is eof, so put in extra one */
  109.             (void) fputc('.', ser_wr_fp);
  110.         if (in_header && strneql(s, "From:", sizeof("From:")-1)) {
  111.                     seen_header = 1;
  112.             seen_fromline = 1;
  113.         }
  114.         if (in_header && s[0] == '\0') {
  115.                     if (seen_header) {
  116.                         in_header = 0;
  117.                     if (!seen_fromline)
  118.                         gen_frompath();
  119.             } else {
  120.                     continue;
  121.             }
  122.         } else if (in_header) {
  123.                 if (valid_header(s))
  124.                     seen_header = 1;
  125.                     else
  126.                                 continue;
  127.         }
  128.         fprintf(ser_wr_fp, "%s\r\n", s);
  129.     }
  130.  
  131.     append_signature();
  132.  
  133.     fprintf(ser_wr_fp, ".\r\n");
  134.     (void) fflush(ser_wr_fp);
  135.     (void) get_server(line, sizeof(line));
  136.     if (*line != CHAR_OK) {
  137.         if (atoi(line) == ERR_POSTFAIL) {
  138.             close_server();
  139.             printf("Article not accepted by server; not posted.\n");
  140.             for (cp = line + 4; *cp && *cp != '\r'; cp++)
  141.                 if (*cp == '\\')
  142.                     putchar('\n');
  143.                 else
  144.                     putchar(*cp);
  145.             exit(1);
  146.         } else {
  147.             close_server();
  148.             fprintf(stderr, "Remote error: %s\n", line);
  149.             exit(1);
  150.         }
  151.     }
  152.  
  153.     /*
  154.      * Close server sends the server a
  155.      * "quit" command for us, which is why we don't send it.
  156.      */
  157.  
  158.     close_server();
  159.  
  160.     exit(0);
  161. }
  162.  
  163. /*
  164.  * append_signature -- append the person's .signature file if
  165.  * they have one.  Limit .signature to MAX_SIGNATURE lines.
  166.  * The rn-style DOTDIR environmental variable is used if present.
  167.  */
  168.  
  169. append_signature()
  170. {
  171.     char    line[256], sigfile[256];
  172.     char    *cp;
  173.     struct    passwd    *passwd;
  174.     FILE    *fp;
  175.     char    *index(), *getenv();
  176.     int    count = 0;
  177.     char    *dotdir;
  178.  
  179.     passwd = getpwuid(getuid());
  180.     if (passwd == NULL)
  181.       return;
  182. #ifdef DO_DOTDIR
  183.     if ((dotdir = getenv("DOTDIR")) == NULL)
  184. #endif
  185.     {
  186.       dotdir = passwd->pw_dir;
  187.     }
  188.  
  189.     if (dotdir[0] == '~') {
  190.       (void) strcpy(sigfile, passwd->pw_dir);
  191.       (void) strcat(sigfile, &dotdir[1]);
  192.     } else {
  193.       (void) strcpy(sigfile, dotdir);
  194.     }
  195.     (void) strcat(sigfile, "/");
  196.     (void) strcat(sigfile, ".signature");
  197.  
  198. #ifdef DEBUG
  199.   fprintf(stderr,"sigfile = '%s'\n", sigfile);
  200. #endif
  201.  
  202.     fp = fopen(sigfile, "r");
  203.     if (fp == NULL)
  204.         return;
  205.  
  206. #ifdef DEBUG
  207.   fprintf(stderr,"sigfile opened OK\n");
  208. #endif
  209.  
  210.     fprintf(ser_wr_fp, "--\r\n");
  211.     while (fgets(line, sizeof (line), fp)) {
  212.         count++;
  213.         if (count > MAX_SIGNATURE) {
  214.             fprintf(stderr,
  215.           "Warning: .signature files should be no longer than %d lines.\n",
  216.             MAX_SIGNATURE);
  217.             fprintf(stderr,
  218.             "(Only %d lines of your .signature were posted.)\n",
  219.             MAX_SIGNATURE);
  220.             break;
  221.         }
  222.         if (cp = index(line, '\n'))
  223.             *cp = '\0';
  224.         fprintf(ser_wr_fp, "%s\r\n", line);
  225.     }
  226.     (void) fclose(fp);
  227. #ifdef DEBUG
  228.     printf(".signature appended (from %s)\n", sigfile);
  229. #endif
  230. }
  231.  
  232.  
  233. /*
  234.  * gen_frompath -- generate From: and Path: lines, in the form
  235.  *
  236.  *    From: user@host.domain (full_name)
  237.  *    Path: host!user
  238.  *
  239.  * This routine should only be called if the message doesn't have
  240.  * a From: line in it.
  241.  */
  242.  
  243. gen_frompath()
  244. {
  245.     char    *full_name;
  246.     char    *cp;
  247.     struct    passwd *passwd;
  248.     char    *index(), *getenv();
  249.  
  250.     passwd = getpwuid(getuid());
  251.  
  252.     full_name = getenv("NAME");
  253.     if (full_name == NULL) {
  254.         full_name = passwd->pw_gecos;
  255.         if ((cp = index(full_name, ',')))
  256.             *cp = '\0';
  257.     }
  258.  
  259. #ifdef DOMAIN
  260. #ifdef HIDDENNET
  261.         fprintf(ser_wr_fp, "From: %s@%s (",
  262.             passwd->pw_name,
  263.             DOMAIN);
  264. #else /* HIDDENNET */
  265.  
  266.     /* A heuristic to see if we should tack on a domain */
  267.  
  268.     cp = index(host_name, '.');
  269.     if (cp)
  270.         fprintf(ser_wr_fp, "From: %s@%s (",
  271.             passwd->pw_name,
  272.             host_name);
  273.     else
  274.         fprintf(ser_wr_fp, "From: %s@%s.%s (",
  275.             passwd->pw_name,
  276.             host_name,
  277.             DOMAIN);
  278. #endif /* HIDDENNET */
  279. #else
  280.     fprintf(ser_wr_fp, "From: %s@%s (",
  281.         passwd->pw_name,
  282.         host_name);
  283. #endif
  284.  
  285.     for (cp = full_name; *cp != '\0'; ++cp)
  286.         if (*cp != '&')
  287.             putc(*cp, ser_wr_fp);
  288.         else {        /* Stupid & hack.  God damn it. */
  289.             putc(toupper(passwd->pw_name[0]), ser_wr_fp);
  290.             fprintf(ser_wr_fp, passwd->pw_name+1);
  291.         }
  292.  
  293.     fprintf(ser_wr_fp, ")\r\n");
  294.  
  295. #ifdef HIDDENNET
  296.     /* Only the login name - nntp server will add uucp name */
  297.     fprintf(ser_wr_fp, "Path: %s\r\n", passwd->pw_name);
  298. #else /* HIDDENNET */
  299.     fprintf(ser_wr_fp, "Path: %s!%s\r\n", host_name, passwd->pw_name);
  300. #endif /* HIDDENNET */
  301. }
  302.  
  303.  
  304. /*
  305.  * strneql -- determine if two strings are equal in the first n
  306.  * characters, ignoring case.
  307.  *
  308.  *    Parameters:    "a" and "b" are the pointers
  309.  *            to characters to be compared.
  310.  *            "n" is the number of characters to compare.
  311.  *
  312.  *    Returns:    1 if the strings are equal, 0 otherwise.
  313.  *
  314.  *    Side effects:    None.
  315.  */
  316.  
  317. strneql(a, b, n)
  318. register char *a, *b;
  319. int    n;
  320. {
  321.     char    lower();
  322.  
  323.     while (n && lower(*a) == lower(*b)) {
  324.         if (*a == '\0')
  325.             return (1);
  326.         a++;
  327.         b++;
  328.         n--;
  329.     }
  330.     if (n)
  331.         return (0);
  332.     else
  333.         return (1);
  334. }
  335.  
  336. /*
  337.  * lower -- convert a character to lower case, if it's
  338.  *    upper case.
  339.  *
  340.  *    Parameters:    "c" is the character to be
  341.  *            converted.
  342.  *
  343.  *    Returns:    "c" if the character is not
  344.  *            upper case, otherwise the lower
  345.  *            case eqivalent of "c".
  346.  *
  347.  *    Side effects:    None.
  348.  */
  349.  
  350. char lower(c)
  351. register char c;
  352. {
  353.     if (isascii(c) && isupper(c))
  354.         c = c - 'A' + 'a';
  355.     return(c);
  356. }
  357.  
  358.  
  359. /*
  360.  * valid_header -- determine if a line is a valid header line
  361.  *
  362.  *    Parameters:    "h" is the header line to be checked.
  363.  *
  364.  *    Returns:     1 if valid, 0 otherwise
  365.  *
  366.  *    Side Effects:    none
  367.  *
  368.  */
  369.  
  370. int valid_header(h)
  371. register char *h;
  372. {
  373.   char *index();
  374.   char *colon, *space;
  375.  
  376.   /*
  377.    * blank or tab in first position implies this is a continuation header
  378.    */
  379.   if (h[0] == ' ' || h[0] == '\t')
  380.     return (1);
  381.  
  382.   /*
  383.    * just check for initial letter, colon, and space to make
  384.    * sure we discard only invalid headers
  385.    */
  386.   colon = index(h, ':');
  387.   space = index(h, ' ');
  388.   if (isalpha(h[0]) && colon && space == colon + 1)
  389.     return (1);
  390.  
  391.   /*
  392.    * anything else is a bad header -- it should be ignored
  393.    */
  394.   return (0);
  395. }
  396.